<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BcDiDoThread类说明文档</title>
    <style>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        h1, h2, h3, h4 {
            color: #0066cc;
            margin-top: 24px;
        }
        h1 {
            border-bottom: 2px solid #0066cc;
            padding-bottom: 10px;
        }
        h2 {
            border-bottom: 1px solid #ccc;
            padding-bottom: 5px;
        }
        code {
            font-family: Consolas, Monaco, 'Andale Mono', monospace;
            background-color: #f5f5f5;
            padding: 2px 4px;
            border-radius: 3px;
            font-size: 0.9em;
        }
        pre {
            background-color: #f5f5f5;
            padding: 10px;
            border-radius: 5px;
            overflow-x: auto;
            font-size: 0.9em;
        }
        table {
            border-collapse: collapse;
            width: 100%;
            margin: 20px 0;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px 12px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        .note {
            background-color: #e6f7ff;
            border-left: 4px solid #1890ff;
            padding: 10px;
            margin: 15px 0;
        }
        .warning {
            background-color: #fff7e6;
            border-left: 4px solid #fa8c16;
            padding: 10px;
            margin: 15px 0;
        }
    </style>
</head>
<body>
    <h1>BcDiDoThread类说明文档</h1>
    
    <h2>1. 类概述</h2>
    <p>BcDiDoThread是一个继承自QThread的线程类，专门用于处理电池簇(Battery Cluster, BC)的数字输入(DI)和数字输出(DO)信号。该类在独立线程中运行，负责监控各种告警信号（如消防、水浸、急停等）并控制相应的输出（如风扇、故障灯等）。</p>
    
    <div class="note">
        <p><strong>注意：</strong>该类是为了解决DI/DO处理中的延时问题而设计的，需要在单独的线程中运行。</p>
    </div>
    
    <h2>2. 主要功能</h2>
    <ul>
        <li>监控多种数字输入信号（DI）并处理相应的告警逻辑</li>
        <li>根据系统状态控制数字输出信号（DO）</li>
        <li>处理各种告警状态（消防、水浸、急停、门禁等）</li>
        <li>控制风扇、故障灯、运行灯等设备</li>
        <li>支持BCMU地址分配功能</li>
        <li>支持断路器脱扣控制</li>
        <li>记录状态变化并生成日志</li>
    </ul>
    
    <h2>3. 类结构</h2>
    
    <h3>3.1 继承关系</h3>
    <p>BcDiDoThread继承自Qt的QThread类，通过重写run()方法实现线程功能。</p>
    <pre><code>class BcDiDoThread : public QThread</code></pre>
    
    <h3>3.2 主要成员变量</h3>
    <table>
        <tr>
            <th>变量名</th>
            <th>类型</th>
            <th>描述</th>
        </tr>
        <tr>
            <td>m_bcDiOldState</td>
            <td>char[30][50]</td>
            <td>存储各电池簇DI信号的历史状态，用于检测状态变化</td>
        </tr>
        <tr>
            <td>m_bcResDiOldState</td>
            <td>char[30][10]</td>
            <td>存储备用DI信号的历史状态</td>
        </tr>
        <tr>
            <td>m_printCount</td>
            <td>int</td>
            <td>打印计数器，用于控制日志输出频率</td>
        </tr>
        <tr>
            <td>m_bcDoLogCount</td>
            <td>int</td>
            <td>DO日志计数器，用于控制DO相关日志输出</td>
        </tr>
        <tr>
            <td>m_runCount</td>
            <td>int</td>
            <td>运行计数器，用于周期性任务控制</td>
        </tr>
        <tr>
            <td>m_oldCtrlFanState</td>
            <td>int[30]</td>
            <td>存储各电池簇风扇的历史控制状态</td>
        </tr>
        <tr>
            <td>m_closeFanReqCount</td>
            <td>int[30]</td>
            <td>风扇关闭请求计数器，用于延时关闭风扇</td>
        </tr>
        <tr>
            <td>m_closeReqStartTime</td>
            <td>QDateTime[30]</td>
            <td>风扇关闭请求的起始时间，用于计算延时</td>
        </tr>
        <tr>
            <td>m_bcmuAddrAllocReq</td>
            <td>int</td>
            <td>BCMU地址分配请求标志</td>
        </tr>
        <tr>
            <td>m_lastBcmuConnFault</td>
            <td>char[30]</td>
            <td>上次BCMU连接故障状态，用于检测变化</td>
        </tr>
    </table>
    
    <h3>3.3 主要方法</h3>
    <table>
        <tr>
            <th>方法名</th>
            <th>返回类型</th>
            <th>描述</th>
        </tr>
        <tr>
            <td>BcDiDoThread(QObject *parent)</td>
            <td>构造函数</td>
            <td>初始化BcDiDoThread对象</td>
        </tr>
        <tr>
            <td>run()</td>
            <td>void</td>
            <td>线程主函数，处理DI/DO逻辑</td>
        </tr>
        <tr>
            <td>dealwithBCDIState(CBattStack *pStack)</td>
            <td>void</td>
            <td>处理电池簇DI状态，包括各种告警信号</td>
        </tr>
        <tr>
            <td>dealwithBCDOState()</td>
            <td>void</td>
            <td>处理电池簇DO状态，控制各种输出设备</td>
        </tr>
        <tr>
            <td>getBCDIValue(CBattBank *pBank, int diIndex)</td>
            <td>int</td>
            <td>获取指定电池簇的DI值</td>
        </tr>
        <tr>
            <td>waitConfSwitchBreaked()</td>
            <td>void</td>
            <td>等待汇流开关断开</td>
        </tr>
        <tr>
            <td>checkBcmuAddressAllocTrigger()</td>
            <td>void</td>
            <td>检查是否有BCMU地址分配的触发条件</td>
        </tr>
        <tr>
            <td>triggerBcmuAddressAlloc()</td>
            <td>void</td>
            <td>操作第一个BCMU的DO以触发地址分配</td>
        </tr>
    </table>
    
    <h2>4. DI/DO策略值说明</h2>
    
    <h3>4.1 DI策略值</h3>
    <p>DI策略值用于定义不同数字输入信号的处理逻辑。</p>
    <table>
        <tr>
            <th>宏定义</th>
            <th>值</th>
            <th>描述</th>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_CONF_SWITCH</td>
            <td>1</td>
            <td>汇流开关反馈</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_ISOL_SWITCH</td>
            <td>2</td>
            <td>隔离开关反馈</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_MAIN_SWITCH</td>
            <td>3</td>
            <td>主断路器反馈</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_THUNDER</td>
            <td>8</td>
            <td>防雷采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_THUNDER2</td>
            <td>108</td>
            <td>#2防雷采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE</td>
            <td>9</td>
            <td>消防采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_WATER</td>
            <td>10</td>
            <td>水浸采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_WATER2</td>
            <td>110</td>
            <td>#2水浸采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_EMERG_STOP</td>
            <td>11</td>
            <td>急停信号采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_EMERG_STOP2</td>
            <td>111</td>
            <td>#2急停信号采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_GAS</td>
            <td>12</td>
            <td>可燃气体采集干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FUSE</td>
            <td>13</td>
            <td>熔断器采集反馈干结点</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE_RELEASE</td>
            <td>14</td>
            <td>消防释放信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_CHARGE_DRIVE</td>
            <td>20</td>
            <td>充电接触器驱动信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_DISCHARGE_DRIVE</td>
            <td>21</td>
            <td>放电接触器驱动信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE_WARN</td>
            <td>22</td>
            <td>消防预警信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_UPS_ALARM</td>
            <td>23</td>
            <td>UPS告警信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_DOOR_ALARM</td>
            <td>24</td>
            <td>门禁告警信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_DOOR_ALARM2</td>
            <td>34</td>
            <td>门禁告警信号2</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE_SPRAY</td>
            <td>25</td>
            <td>消防喷洒信号</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE_FAULT</td>
            <td>26</td>
            <td>消防故障</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_FIRE_MANUAL</td>
            <td>27</td>
            <td>消防手动/自动</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_POWER_OFF</td>
            <td>30</td>
            <td>市电断电</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_BMS_LOCAL</td>
            <td>31</td>
            <td>BMS就地</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_BMS_REMOTE</td>
            <td>32</td>
            <td>BMS远方</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_AC_FAULT</td>
            <td>41</td>
            <td>空调机组故障</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_LIQUID_FAULT</td>
            <td>42</td>
            <td>液冷机组故障</td>
        </tr>
        <tr>
            <td>BC_DI_STRATEGY_RES1 ~ RES8</td>
            <td>51 ~ 58</td>
            <td>备用信号1 ~ 8</td>
        </tr>
    </table>
    
    <h3>4.2 DO策略值</h3>
    <p>DO策略值用于定义不同数字输出信号的控制逻辑。</p>
    <table>
        <tr>
            <th>宏定义</th>
            <th>值</th>
            <th>描述</th>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_ADDR_ALLOC</td>
            <td>81</td>
            <td>BCMU地址分配</td>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_FAN</td>
            <td>25</td>
            <td>风扇控制</td>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_TRIP_SWITCH</td>
            <td>102</td>
            <td>断路器脱扣</td>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_AC_TRIP_SWITCH</td>
            <td>103</td>
            <td>交流断路器脱扣</td>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_AC_TRIP_SWITCH2</td>
            <td>109</td>
            <td>交流断路器脱扣2</td>
        </tr>
        <tr>
            <td>BC_DO_STRATEGY_AC_TRIP_SWITCH3</td>
            <td>110</td>
            <td>交流断路器脱扣3</td>
        </tr>
    </table>
    
    <h2>5. 关键功能实现</h2>
    
    <h3>5.1 告警状态判断</h3>
    <p>通过getAlarmState函数判断是否触发告警：</p>
    <pre><code>char getAlarmState(char state, char alarmValue)
{
    return (alarmValue > 0) ? (state > 0) : (state == 0);
}</code></pre>
    <p>该函数根据报警值（alarmValue）和状态（state）来判断是否触发报警：</p>
    <ul>
        <li>当 alarmValue > 0 时，如果 state > 0，则返回 1（报警）</li>
        <li>当 alarmValue <= 0 时，如果 state == 0，则返回 1（报警）</li>
        <li>其他情况下返回 0（不报警）</li>
    </ul>
    
    <h3>5.2 DI值获取</h3>
    <p>通过getBCDIValue函数获取指定电池簇的DI值：</p>
    <pre><code>int BcDiDoThread::getBCDIValue(CBattBank *pBank, int diIndex)
{
    // 安全检查，防止空指针异常
    if (!pBank) {
        return 0;
    }
    
    // 使用switch语句替代if-else链，提高代码可读性和性能
    switch (diIndex) {
        case 0: return pBank->usDI1;     // DI1输入
        case 1: return pBank->usDI2;     // DI2输入
        case 2: return pBank->usDI3;     // DI3输入
        case 3: return pBank->usDI4;     // DI4输入
        case 4: return pBank->usDI5;     // DI5输入
        case 5: return pBank->usDI6;     // DI6输入
        case 6: return pBank->aBankTemp[0]; // 温度传感器1
        case 7: return pBank->aBankTemp[1]; // 门禁
        default: return 0;               // 无效索引返回0
    }
}</code></pre>
    
    <h3>5.3 汇流开关断开等待</h3>
    <p>通过waitConfSwitchBreaked函数等待汇流开关断开：</p>
    <pre><code>void BcDiDoThread::waitConfSwitchBreaked()
{
    // 检查是否配置了汇流开关且当前汇流开关状态为闭合
    if (!KgGlobalData::ms_hlkgStrategy.diCfgList.empty() &&
        KgGlobalData::ms_pStack->aConfSwitchState > 0)
    {
        const int maxWaitCount = 90;  // 最大等待次数，90次 * 100ms = 9秒
        for (int k = 0; k < maxWaitCount; ++k)
        {
            this->msleep(100);  // 每次暂停100毫秒
            // 检查汇流开关是否已断开（状态值为0表示断开）
            if (KgGlobalData::ms_pStack->aConfSwitchState == 0)
            {
                // 汇流开关已断开，输出3次提示信息后退出
                for (int m = 0; m < 3; ++m)
                {
                    printf("*******************汇流开关已断开。\n");
                }
                break;  // 提前退出等待循环
            }
        }
    }
}</code></pre>
    
    <h3>5.4 DI状态处理</h3>
    <p>dealwithBCDIState函数处理各种DI信号，包括消防、水浸、急停、门禁等告警信号。该函数会根据不同的策略值执行不同的处理逻辑，并在状态变化时记录日志。</p>
    
    <h3>5.5 DO状态处理</h3>
    <p>dealwithBCDOState函数处理各种DO信号，包括故障灯、运行灯、风扇控制等。该函数会根据系统状态和告警情况控制相应的输出设备。</p>
    
    <h3>5.6 BCMU地址分配</h3>
    <p>通过checkBcmuAddressAllocTrigger和triggerBcmuAddressAlloc函数实现BCMU地址分配功能。</p>
    
    <h2>6. 使用示例</h2>
    
    <h3>6.1 创建和启动线程</h3>
    <pre><code>// 创建BcDiDoThread对象
BcDiDoThread *pBcDiDoThread = new BcDiDoThread(this);

// 启动线程
pBcDiDoThread->start();

// 等待线程结束（如果需要）
// pBcDiDoThread->wait();</code></pre>
    
    <h3>6.2 配置DI策略</h3>
    <pre><code>// 创建DI策略对象
DI_STU diStg;
diStg.diIndex = 0;  // DI1
diStg.iStrategy = BC_DI_STRATEGY_FIRE;  // 消防采集干结点
diStg.alarmValue = 1;  // 当DI值>0时触发告警

// 添加到全局策略列表
KgGlobalData::ms_bcDiList.append(diStg);</code></pre>
    
    <h3>6.3 配置DO策略</h3>
    <pre><code>// 创建DO策略对象
DOStrategy doStg;
doStg.doIndex = 0;  // DO1
doStg.iStrategy = BC_DO_STRATEGY_FAN;  // 风扇控制

// 添加到全局策略列表
KgGlobalData::ms_bcDoList.append(doStg);</code></pre>
    
    <div class="warning">
        <p><strong>警告：</strong>在使用BcDiDoThread类时，需要确保相关的全局数据（如KgGlobalData::ms_bcDiList、KgGlobalData::ms_bcDoList等）已正确初始化。</p>
    </div>
    
    <h2>7. 注意事项</h2>
    <ul>
        <li>BcDiDoThread类需要在单独的线程中运行，以避免阻塞主线程</li>
        <li>该类依赖于KgGlobalData、CBattStack、CBattBank等相关类</li>
        <li>在处理DI/DO信号时，需要注意信号的有效性和状态变化</li>
        <li>部分功能（如BCMU地址分配）可能需要特定的硬件支持</li>
        <li>在使用该类时，需要确保相关的全局数据已正确初始化</li>
        <li>该类中的部分功能可能与特定项目相关，如WTGZ_PRJ（威腾广州项目）</li>
    </ul>
    
    <h2>8. 版本历史</h2>
    <table>
        <tr>
            <th>日期</th>
            <th>版本</th>
            <th>描述</th>
        </tr>
        <tr>
            <td>2024-11-20</td>
            <td>最新</td>
            <td>添加BCMU地址分配和风扇控制功能</td>
        </tr>
        <tr>
            <td>2024-10-26</td>
            <td>-</td>
            <td>添加断路器脱扣功能</td>
        </tr>
        <tr>
            <td>2024-9-29</td>
            <td>-</td>
            <td>添加dealwithBCDOState函数</td>
        </tr>
        <tr>
            <td>2024-9-5</td>
            <td>-</td>
            <td>更新全局告警状态处理</td>
        </tr>
        <tr>
            <td>2024-8-28</td>
            <td>-</td>
            <td>添加dealwithBCDIState函数</td>
        </tr>
        <tr>
            <td>2024-2-3</td>
            <td>-</td>
            <td>添加空调机组故障和液冷机组故障功能</td>
        </tr>
        <tr>
            <td>2023-12-25</td>
            <td>-</td>
            <td>添加BMS就地功能</td>
        </tr>
        <tr>
            <td>2023-11-9</td>
            <td>-</td>
            <td>添加消防手动/自动和市电断电功能</td>
        </tr>
        <tr>
            <td>2023-8-19</td>
            <td>-</td>
            <td>添加备用信号功能</td>
        </tr>
        <tr>
            <td>2023-5-4</td>
            <td>-</td>
            <td>添加门禁告警信号2功能</td>
        </tr>
        <tr>
            <td>2022-12-21</td>
            <td>-</td>
            <td>添加消防故障功能</td>
        </tr>
        <tr>
            <td>2022-12-10</td>
            <td>-</td>
            <td>添加消防喷洒信号功能</td>
        </tr>
        <tr>
            <td>2022-4-6</td>
            <td>-</td>
            <td>添加消防释放信号功能</td>
        </tr>
        <tr>
            <td>2022-3-27</td>
            <td>-</td>
            <td>添加熔断器采集反馈干结点功能</td>
        </tr>
    </table>
    
    <hr>
    <p><em>文档最后更新时间：2024年11月</em></p>
</body>
</html>